package com.linkoog.devtools.icon_viewer.converters;

import com.linkoog.devtools.icon_viewer.ImageToIconConverter;
import com.linkoog.devtools.icon_viewer.core.Base64;
import com.linkoog.devtools.icon_viewer.core.IconType;
import com.linkoog.devtools.icon_viewer.core.ImageWrapper;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.paint.PaintUtil;
import com.intellij.util.IconUtil;
import com.intellij.util.ImageLoader;
import com.intellij.util.JBHiDPIScaledImage;
import com.intellij.util.ui.ImageUtil;
import com.intellij.util.ui.UIUtil;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class RegularImageConverter implements ImageToIconConverter {

    private static final Logger LOGGER = Logger.getInstance(RegularImageConverter.class);

    private static final List<String> extensions = new CopyOnWriteArrayList<>(Arrays.asList("jpeg", "jpg", "png", "wbmp", "gif", "bmp"));

    private static final int WIDTH = 16;
    private static final int HEIGHT = 16;

    @Override
    public Collection<String> getExtensions() {
        return extensions;
    }

    @Override
    public IconType getIconType() {
        return IconType.IMG;
    }

    @Override
    public Image loadImage(ByteArrayInputStream byteArrayInputStream, VirtualFile virtualFile) throws IOException {
        return ImageLoader.loadFromStream(byteArrayInputStream);
    }

    @Override
    public Icon convert(VirtualFile canonicalFile, String canonicalPath) throws IOException {
        try {
            Icon imageIcon = loadImageIcon(canonicalFile);
            if (imageIcon != null) return imageIcon;
            return new ImageIcon(ImageIO.read(new File(canonicalFile.getPath())).getScaledInstance(WIDTH, HEIGHT, Image.SCALE_SMOOTH));
        } catch (IOException e) {
        }
        return null;
    }

    @Override
    public String toBase64(ImageWrapper imageWrapper) {

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            Image image = imageWrapper.getImage();
            if (image instanceof JBHiDPIScaledImage){
                image = ((JBHiDPIScaledImage)image).getDelegate();
            }

            /*if (image instanceof ToolkitImage){
                image = ((ToolkitImage)image).getBufferedImage();
            } */

            if (image instanceof RenderableImage) {
                GraphicsConfiguration graphicsConfiguration = null;
                if (!GraphicsEnvironment.isHeadless()){
                    graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
                }

                BufferedImage bufferedImage = UIUtil.createImage(
                        graphicsConfiguration,
                        image.getWidth(null),
                        image.getHeight(null),
                        BufferedImage.TYPE_INT_RGB,
                        PaintUtil.RoundingMode.ROUND
                );
                bufferedImage.getGraphics().drawImage(image, 0, 0, null);
                image = bufferedImage;
            }

            ImageIO.write((RenderedImage) image, "png", outputStream);
        } catch (IOException e) {
            //LOG.warn(e.message)
        }
        return Base64.encode(outputStream.toByteArray());
    }




    private Icon loadImageIcon(VirtualFile virtualFile) {
        try {
            Image scaleImage = loadImage(virtualFile.getInputStream());
            if (scaleImage != null) {
                return IconUtil.createImageIcon(scaleImage);
            }
        } catch (IOException e) {
            //LOG.warn(e.message)
        }
        return null;
    }

    private Image loadImage(InputStream inputStream) throws IOException{
        try (ImageInputStream input = ImageIO.createImageInputStream(inputStream)) {
            Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
            while (readers.hasNext()) {
                ImageReader reader = readers.next();
                try {
                    reader.setInput(input);
                    BufferedImage originalImage = reader.read(0);
                    return ImageUtil.scaleImage(originalImage, WIDTH, HEIGHT);
                } finally {
                    reader.dispose();
                }
            }
        }
        return null;
    }

}
